package com.tucc.hello;

import java.lang.reflect.Array;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Map;

/**
 * @author tucc
 * @description todo
 * @package com.tucc.hello
 * @date 2021/6/17
 **/
public class DateTest {

    public static Integer CNST_DIGIT_100 = 100;

    public static void main(String[] args) {
        Integer sHoldBeginFirstDate = 20100531;
        Integer sHoldBeginDate = 20100630;
        Integer sHoldEndDate = 20100701;
        Integer miniHoldDays = 1;
        int cycles = calMaxRdmDateCycles4CorrespondingDate(sHoldBeginFirstDate, sHoldBeginDate,
                    sHoldEndDate, miniHoldDays);
        System.out.println(cycles);
        cycles = calMaxRdmDateCycles4CorrespondingDate2(sHoldBeginFirstDate, sHoldBeginDate,
                sHoldEndDate, miniHoldDays);
        System.out.println(cycles);
//        Calendar calendar = Calendar.getInstance();
//        calendar.set(2010, 5, 30);
//
//        while (true) {
//            int year = calendar.get(Calendar.YEAR);
//            int month = calendar.get(Calendar.MONTH);
//            int day = calendar.get(Calendar.DATE);
//            sHoldEndDate = year * 10000 + (month + 1) * 100 + day;
//            int cycles = calMaxRdmDateCycles4CorrespondingDate(sHoldBeginFirstDate, sHoldBeginDate,
//                    sHoldEndDate, miniHoldDays);
//
//            System.out.println(String.format("%d-%d-%d cycles: %d",
//                    year, month + 1, day, cycles));
//            if (month == 06 && day == 31) {
//                break;
//            }
//            calendar.add(Calendar.DATE, 1);
//            if(sHoldEndDate == 20100630){
//                sHoldBeginDate = 20100630;
//            }
//        }

    }


    public static Integer calMaxRdmDateCycles4CorrespondingDate(Integer sHoldBeginFirstDate,
                                                                Integer sHoldBeginDate, Integer sHoldEndDate, Integer miniHoldDays) {
        // 用第一次的循环持有开始日期 计算对日
        int firstDay = sHoldBeginFirstDate % CNST_DIGIT_100;
        int lastEndDay = sHoldBeginDate % CNST_DIGIT_100;
        long months = Ta5DateUtils.betweenMonthes(sHoldEndDate, sHoldBeginDate);
        long totalMonths = Ta5DateUtils.betweenMonthes(sHoldEndDate, sHoldBeginFirstDate);
        // 计算当前经过的周期数 向上取整
        int cycles = (int) Math.ceil(totalMonths * 1.0 / miniHoldDays);
        if (months == 0) {
            // 当月已经退出过，且退出日的天 比 初始日的天 大
            if (lastEndDay >= firstDay) {
                // 则说明已经是下一个周期
                cycles = (int) Math.ceil(totalMonths * 1.0 / miniHoldDays) + 1;
            }
        } else {
            // 已经超出循环月的， 也就是说上次循环到月底，但月底非工作日，递推下一日发生跳月的情况
            // 也说明此时是跳月的第一个工作日，此时可以退出
            if ((months > miniHoldDays)) {
                // 按减1个周期算退出日
                cycles = cycles - 1;
            } else {
                // 如果出现 连续2个月都 递推了一个工作日变成下个月的情况
                // 比如 0130 0301 0401， 但要排除月底退出的情况，
                if (months == miniHoldDays &&  lastEndDay < firstDay && lastEndDay < 28) {
                    cycles = cycles - 1;
                }
            }
        }
        return cycles;
    }

    public static int CNST_DIGIT_0 = 0;
    public static int CNST_DIGIT_1 = 1;
    public static int CNST_DIGIT_28 = 28;


    public static Integer calMaxRdmDateCycles4CorrespondingDate2(Integer sHoldBeginFirstDate,
                                                                Integer sHoldBeginDate, Integer sHoldEndDate, Integer miniHoldDays) {
        // 用第一次的循环持有开始日期 计算对日
        int firstDay = sHoldBeginFirstDate % CNST_DIGIT_100;
        int lastEndDay = sHoldBeginDate % CNST_DIGIT_100;
        long months = Ta5DateUtils.betweenMonthes(sHoldEndDate, sHoldBeginDate);
        long totalMonths = Ta5DateUtils.betweenMonthes(sHoldEndDate, sHoldBeginFirstDate);
        // 计算当前经过的周期数 向上取整
        int cycles = (int) Math.ceil(totalMonths * 1.0 / miniHoldDays);
        if (months == CNST_DIGIT_0) {
            // 当月已经退出过，且退出日的天 比 初始日的天 大
            if (lastEndDay >= firstDay) {
                // 则说明已经是下一个周期
                cycles = cycles + CNST_DIGIT_1;
            }
        } else {
            // 已经超出循环月的， 也就是说上次循环到月底，但月底非工作日，递推下一日发生跳月的情况
            // 也说明此时是跳月的第一个工作日，此时可以退出
            if ((months > miniHoldDays)) {
                // 按减1个周期算退出日
                cycles = cycles - CNST_DIGIT_1;
            } else {
                // 如果出现 连续2个月都 递推了一个工作日变成下个月的情况
                // 比如 0130 0301 0401， 但要排除非跳月和月底退出的情况，
                // lastEndDay < firstDay 排除了非跳月的情况 但可能是 0130 0228这类上个月是月底的情况
                // lastEndDay < 28 排除了月底的情况 上个月如果是跳月的不可能 >= 28
                if (months == miniHoldDays && lastEndDay < firstDay && lastEndDay < CNST_DIGIT_28) {
                    cycles = cycles - CNST_DIGIT_1;
                }
            }
        }
        return cycles;
    }
}

class Ta5DateUtils {
    public static Long betweenMonthes(Integer before, Integer after) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        Calendar be = Calendar.getInstance();
        Calendar af = Calendar.getInstance();

        try {
            be.setTime(simpleDateFormat.parse(String.valueOf(before)));
            af.setTime(simpleDateFormat.parse(String.valueOf(after)));
        } catch (ParseException var9) {
            var9.printStackTrace();
        }

        long inOneYear = (long) (af.get(2) - be.get(2));
        long outOneYear = (long) ((af.get(1) - be.get(1)) * 12);
        return Math.abs(inOneYear + outOneYear);
    }

    public static Boolean smaller(Integer val1, Integer val2) {
        Integer defaultValue = 0;
        Integer tmpVal1 = nvl(val1, defaultValue);
        Integer tmpVal2 = nvl(val2, defaultValue);
        return (tmpVal1.compareTo(tmpVal2) < 0);
    }

    public static <T> T nvl(T srcValue, T replaceValue) {
        return isEmpty(srcValue) ? replaceValue : srcValue;
    }

    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        } else if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0;
        } else if (obj.getClass().isArray()) {
            return Array.getLength(obj) == 0;
        } else if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        } else {
            return obj instanceof Map ? ((Map) obj).isEmpty() : false;
        }
    }
}
